﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace Mirkuz.Mapping
{
    public partial class MapBox : UserControl
    {
        int tX;
        int tY;
        int prevx;
        int prevy;
        bool move;

        Bitmap bk;

        public MapTrack TrackDisplayed;

        public MapBox()
        {
            InitializeComponent();
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                move = true;
                prevy = e.Y;
                prevx = e.X;
            }
        }
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (move)
            {
                tX += prevx - e.X;
                tY += prevy - e.Y;
                prevx = e.X;
                prevy = e.Y;

                RedrawBackBuffer();
                pictureBox1.Invalidate();
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (move)
            {
                move = false;
                tX += prevx - e.X;
                tY += prevy - e.Y;

                RedrawBackBuffer();
                pictureBox1.Invalidate();
            }

        }
        void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (bk == null)
                return;

            lock (bk)
            {
                /*swap buffer*/
                e.Graphics.DrawImage(bk, 0, 0);
            }
        }

        private int ToPixelsX(Double x)
        {
            return (pictureBox1.Width / 2) + ToPixels(x);
        }
        private int ToPixelsY(Double y)
        {
            return (pictureBox1.Height / 2) + ToPixels(y);
        }
        private int ToPixels(double d)
        {
            return (int)(d*10 / (double)tkZoom.Value);
        }

        private void tkZoom_ValueChanged(object sender, EventArgs e)
        {
            RedrawBackBuffer();

            pictureBox1.Invalidate();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            RedrawBackBuffer();

            if (TrackDisplayed != null)
                pictureBox1.Invalidate();
        }


        private void RedrawBackBuffer()
        {
            /*bitmap per disegno offscreen*/
            if (bk==null)
                bk = new Bitmap(pictureBox1.Width, pictureBox1.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb565);

            lock (bk)
            {
                Graphics goff = Graphics.FromImage(bk);
                goff.Clear(Color.White);
                try
                {
                    /*disegno la traccia*/
                    if (TrackDisplayed != null)
                    {
                        /*disegno al massimo 50 punti*/
                        int inc = 0;
                        inc = TrackDisplayed.TrackPoints.Count / 50;
                        if (inc <= 1)
                            inc = 1;

                        for (int i = TrackDisplayed.TrackPoints.Count - 2; i >= 0; i -= inc)
                        {
                            try
                            {
                                int x1 = ToPixelsX(TrackDisplayed.TrackPoints[i + inc].XDistanceMeters(TrackDisplayed.LastPoint)) - tX;
                                int x2 = ToPixelsX(TrackDisplayed.TrackPoints[i].XDistanceMeters(TrackDisplayed.LastPoint)) - tX;
                                int y1 = ToPixelsY(TrackDisplayed.TrackPoints[i + inc].YDistanceMeters(TrackDisplayed.LastPoint)) - tY;
                                int y2 = ToPixelsY(TrackDisplayed.TrackPoints[i].YDistanceMeters(TrackDisplayed.LastPoint)) - tY;

                                //solo se il punto è visibile lo disegno
                                if (((x1 >= 0 || x1 <= bk.Width) && (y1 >= 0 || y1 <= bk.Height))
                                 || ((x2 >= 0 || x2 <= bk.Width) && (y2 >= 0 || y2 <= bk.Height)))
                                {
                                    goff.DrawLine(new Pen(Color.Red, 5), x1, y1, x2, y2);
                                }
                            }
                            catch { }
                        }

                        //posizione attuale sempre nel centro
                        goff.DrawEllipse(new Pen(Color.Blue, 10),
                                                        pictureBox1.Width / 2 - tX, pictureBox1.Height / 2 - tY,
                                                        10, 10);
                    }

                }
                catch { }
                goff.Dispose();
            }
        }

        private void cmdCenter_Click(object sender, EventArgs e)
        {
            tX = 0;
            tY = 0;
            RedrawBackBuffer();
            pictureBox1.Invalidate();
        }
    }
}
